{-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
{-# LANGUAGE FlexibleContexts, TypeFamilies, 
  FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}

module Vector4D where

import Data.VectorSpace hiding (Scalar)
import qualified Data.VectorSpace as VS

import Math
import Projectable
import Control.Parallel.Strategies

data Vector4 = V4 !Scalar !Scalar !Scalar !Scalar deriving (Show,Eq,Read)

-- | Construct a 4D vector
vector4 :: Scalar -> Scalar -> Scalar -> Scalar -> Vector4
vector4 = V4

{-# INLINE vector4 #-} 

instance Project4 Vector4 where
  project4 (V4 x y z w) = (x,y,z,w)
  compose4 (x,y,z,w) = (V4 x y z w)

instance ProjectX Vector4 where
  getX (V4 x _ _ _) = x
  mapX f (V4 x y z w) = V4 (f x) y z w

instance ProjectY Vector4 where
  getY (V4 _ y _ _) = y
  mapY f (V4 x y z w) = V4 x (f y) z w

instance ProjectZ Vector4 where
  getZ (V4 _ _ z _) = z
  mapZ f (V4 x y z w) = V4 x y (f z) w

instance ProjectW Vector4 where
  getW (V4 _ _ _ w) = w
  mapW f (V4 x y z w) = V4 x y z (f w)

instance AdditiveGroup Vector4 where
  zeroV = V4 0 0 0 0
  V4 x1 y1 z1 w1 ^+^ V4 x2 y2 z2 w2 = V4 (x1+x2) (y1+y2) (z1+z2) (w1+w2)
  negateV (V4 x y z w) = V4 (negate x) (negate y) (negate z) (negate w)

instance VectorSpace Vector4 where
  type VS.Scalar (Vector4) = Scalar
  s *^ V4 x y z w = V4 (s*x) (s*y) (s*z) (s*w)

instance InnerSpace Vector4 where
  V4 x1 y1 z1 w1 <.> V4 x2 y2 z2 w2 = x1*x2+y1*y2+z1*z2+w1*w2

instance NFData (Vector4)


 
